//
// Created by QU on 24-6-19.
//
#include <iostream>
#include <fstream>
#include <sstream>
#include <functional>
#include <utility>
#include <memory>
#include <vector>
#include <map>
#include <set>

#include <chrono>
#include <format>


using std::cout, std::cin, std::endl;
using namespace std::literals;

// 用户定义字面量
// 在chrono头文件中, 你可以使用类似于 1ms, 1s, 1h等等来定义一个事件间隔. 你知道这个实在怎样实现的吗?

// 其实这个是c++20的新功能.
/// https://zh.cppreference.com/w/cpp/language/user_literal

/**
 * *字面量运算符仅允许下列形参列表：
 *    ( const char* )	(1)
 *    ( unsigned long long int )	(2)
 *    ( long double )	(3)
 *    ( char )	(4)
 *    ( wchar_t )	(5)
 *    ( char8_t )	(6)	(C++20 起)
 *    ( char16_t )	(7)
 *    ( char32_t )	(8)
 *    ( const char*, std::size_t )	(9)
 *    ( const wchar_t*, std::size_t )	(10)
 *    ( const char8_t*, std::size_t )	(11)	(C++20 起)
 *    ( const char16_t*, std::size_t )	(12)
 *    ( const char32_t*, std::size_t )	(13)
 *
 */

// 用户定义后缀 必须以下划线 _ 开始：不以下划线开始的后缀为标准库提供的字面量运算符所保留。
// 用户定义后缀 也不能包含双下划线 __：此类后缀也被保留。
std::string operator""_aquawius (const char * str, size_t size)
{
    std::string s(str);
    std::cout << s << '\n';
    return std::move(s);
}

void operator""_int (unsigned long long int _int)
{
    std::cout << _int << '\n';
}

/*
 * 不知道为什么, 这段代码并不能通过编译, 即使我使用了最新的gcc14.
struct A
{
    constexpr A(const char* s) noexcept: str(s) {};
    const char* str;
};

template <A a>
constexpr auto operator""_f()
{
    return []<typename... T>(T... Args)
    {
        return std::format(a.str, Args...);
    };
}
*/

int main(int argc, char const *argv[]) {
    const auto myString = "Hello, aquawius!"_aquawius;
    std::cout << "Converted string: " << myString << std::endl;
    123123_int;

    // 用户定义的以_开头, 标准库中定义的没有下划线
    std::cout << "string"s << std::endl;

    // mq-b的例子: 利用用户定义字面量使用模版实现类似std::format的效果.
    // std::cout << "{} ** {} "_f(5, 5.56) << "\n";

    return 0;
}

/*

"C:\Program Files\CMake\bin\cmake.exe" --build C:\coding\modern-cpp-mqb\cmake-build-debug-w64devkit-gcc-14 --target literal_user_defined -- -j 10
[ 50%] Building CXX object CMakeFiles/literal_user_defined.dir/literal_user_defined.cpp.obj
C:\coding\modern-cpp-mqb\literal_user_defined.cpp: In function 'int main(int, const char**)':
C:\coding\modern-cpp-mqb\literal_user_defined.cpp:87:18: error: no matching function for call to 'operator""_f<"{} ** {} ">()'
87 |     std::cout << "{} ** {} "_f(5, 5.56) << "\n";
|                  ^~~~~~~~~~~~~
C:\coding\modern-cpp-mqb\literal_user_defined.cpp:64:16: note: candidate: 'template<A a> constexpr auto operator""_f()'
64 | constexpr auto operator""_f()
|                ^~~~~~~~
C:\coding\modern-cpp-mqb\literal_user_defined.cpp:64:16: note:   template argument deduction/substitution failed:
C:\coding\modern-cpp-mqb\literal_user_defined.cpp:87:18: error: '"{} ** {} "' is not a valid template argument of type 'const char*' because '"{} ** {} "' is not a variable or function
87 |     std::cout << "{} ** {} "_f(5, 5.56) << "\n";
|                  ^~~~~~~~~~~~~
make[3]: *** [CMakeFiles\literal_user_defined.dir\build.make:75: CMakeFiles/literal_user_defined.dir/literal_user_defined.cpp.obj] Error 1
make[2]: *** [CMakeFiles\Makefile2:140: CMakeFiles/literal_user_defined.dir/all] Error 2
make[1]: *** [CMakeFiles\Makefile2:147: CMakeFiles/literal_user_defined.dir/rule] Error 2
make: *** [Makefile:149: literal_user_defined] Error 2

*/